import * as Cesium from '@cesiumjs';

const $defaultOpts = {
  size: 0.02, //最好小于0.02
  speed: 60.0,
}

class FogEffect {

  constructor(viewer, options) {
    if (!viewer) {
      console.error('no viewer object!')
      throw new Error('no viewer object!')
    };
    this._viewer = viewer;
    this.stage = undefined;
    this.options = { ...$defaultOpts, ...options}

    this.defineProperties();
    this.init();
  }

  defineProperties() {
    const _this = this;
    const {options:opt} = this;
    Object.defineProperty(this, "size", {
      get(){return opt.size;},
      set(val){ opt.size = val }
    })
    Object.defineProperty(this, "speed", {
      get(){return opt.speed;},
      set(val){ opt.speed = val }
    })
    Object.defineProperty(this, "show", {
      get(){return _this.stage&&_this.stage.enabled;},
      set(val){ _this.stage&&(_this.stage.enabled = val) }
    })
    Object.defineProperty(this, "viewer", {
      get(){return _this._viewer;}
    })
  }

  init() {
    this.destroy();

    this.stage = new Cesium.PostProcessStage({
      name: 'czm_snow',
      fragmentShader: this.fog(),
      uniforms: {
        size: () => {
          return this.size;
        },
        speed: () => {
          return this.speed;
        }
      }
    });

    this.viewer.scene.postProcessStages.add(this.stage);
  }

  destroy() {
    const {viewer,stage} = this;
    stage && viewer.scene.postProcessStages.remove(stage);
    // stage && stage.destroy();
    this.stage = null;
  }

  //雾气色器
  fog() {
    return 'uniform sampler2D colorTexture;\n' +
      '  uniform sampler2D depthTexture;\n' +
      '  varying vec2 v_textureCoordinates;\n' +
      '  void main(void)\n' +
      '  {\n' +
      '      vec4 origcolor=texture2D(colorTexture, v_textureCoordinates);\n' +
      '      vec4 fogcolor=vec4(0.8,0.8,0.8,0.5);\n' +
      '      float depth = czm_readDepth(depthTexture, v_textureCoordinates);\n' +
      '      vec4 depthcolor=texture2D(depthTexture, v_textureCoordinates);\n' +
      '      float f=(depthcolor.r-0.6)/0.2;\n' +
      '      if(f<0.0) f=0.0;\n' +
      '      else if(f>1.0) f=1.0;\n' +
      '      gl_FragColor = mix(origcolor,fogcolor,f);\n' +
      '   }';
  }
}

/**
 * 
 var fragmentShaderSource =
     'float getDistance(sampler2D depthTexture, vec2 texCoords){ \n' +
     '    float depth = czm_unpackDepth(texture2D(depthTexture, texCoords)); \n' +
     '    if (depth == 0.0) { \n' +
     '        return czm_infinity; \n' +
     '    } \n' +
     '    vec4 eyeCoordinate = czm_windowToEyeCoordinates(gl_FragCoord.xy, depth); \n' +
     '    return -eyeCoordinate.z / eyeCoordinate.w; \n' +
     '} \n' +
     'float interpolateByDistance(vec4 nearFarScalar, float distance){ \n' +
     '    float startDistance = nearFarScalar.x; \n' +
     '    float startValue = nearFarScalar.y; \n' +
     '    float endDistance = nearFarScalar.z; \n' +
     '    float endValue = nearFarScalar.w; \n' +
     '    float a = clamp((distance - startDistance) / (endDistance - startDistance), 0.0, 1.0); \n' +
     '    return mix(startValue, endValue, a); \n' +
     '} \n' +
     'vec4 alphaBlend(vec4 finalFogColor, vec4 sceneColor){ \n' +
     '    return finalFogColor * vec4(finalFogColor.aaa, 1.0) + sceneColor * (1.0 - finalFogColor.a); \n' +
     '} \n' +
     'uniform sampler2D colorTexture; \n' +
     'uniform sampler2D depthTexture; \n' +
     'uniform vec4 fogByDistance; \n' +
     'uniform vec4 fogColor; \n' +
     'varying vec2 v_textureCoordinates; \n' +
     'void main(void){ \n' +
     '    float distance = getDistance(depthTexture, v_textureCoordinates); \n' +
     '    vec4 sceneColor = texture2D(colorTexture, v_textureCoordinates); \n' +
     '    float blendAmount = interpolateByDistance(fogByDistance, distance); \n' +
     '    vec4 finalFogColor = vec4(fogColor.rgb, fogColor.a * blendAmount); \n' +
     '    gl_FragColor = alphaBlend(finalFogColor, sceneColor); \n' +
     '} \n';
 
   const fogByDistance = new Cesium.Cartesian4(10, 0.0, 50000, 1.0);
   const fogColor = Cesium.Color.WHITE;
   const stage = new Cesium.PostProcessStage({
     fragmentShader: fragmentShaderSource,
     uniforms: {
       fogByDistance,
       fogColor
     }
   });
 
   var postProcessStage = viewer.scene.postProcessStages.add(stage);
 
 */

export default FogEffect;
